package com.m3958.firstgwt.server.dao;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityManager;

import com.m3958.firstgwt.client.types.ServerErrorCode;
import com.m3958.firstgwt.server.model.BaseTreeModel;
import com.m3958.firstgwt.server.session.ErrorMessages;
import com.m3958.firstgwt.server.types.SmartError;
import com.m3958.firstgwt.server.types.TreeModel;
import com.m3958.firstgwt.shared.type.SmartConstants;
import com.google.inject.persist.Transactional;

/**
 * @author <a href="jianglibo@gmail.com">Dave Rapin</a>
 * 
 *         <p>
 *         Abstract implementation for data access classes. Extending this class
 *         give's us the benefit of generic working find, findAll, save, and
 *         remove methods.
 * 
 * @param <T>
 * 
 */
public abstract class BaseTreeDao<T extends BaseTreeModel<T>> extends BaseDao<T> implements IDao<T> {

	public BaseTreeDao(Class<T> persistentClass) {
		super(persistentClass);
	}
	
	protected void setParent(TreeModel<T> tmodel){
		int pint = getReqPs().getParentId();
		if(pint != SmartConstants.NONE_EXIST_MODEL_ID){
			T p = find(pint);
			tmodel.setParent(p);
			p.addChildren(tmodel);
			p.setChildrenNum(p.getChildren().size());
		}
	}
	
	@Override
	@Transactional
	public void smartPersistBaseModel(T baseModel){
		if(getReqPs() != null){
			setParent(baseModel);
		}
		super.smartPersistBaseModel(baseModel);
	}
	
	@Transactional
	@Override
	public T smartUpdateBaseModel(T model){
			T oldModel = find(model.getId());

			int pid = getReqPs().getParentId();
			TreeModel<T> op = oldModel.getParent();
			
			if(pid == SmartConstants.NONE_EXIST_MODEL_ID){//提升到根目录
				if(op != null){
					op.removeChildren(oldModel);//原來的目錄要刪除
					op.setChildrenNum(op.getChildren().size());
				}
				oldModel.setParent(null);
			}else{
				T p = find(pid);
				if(op != null){
					if(op.getId() != pid){
						p.addChildren(oldModel);//新的父目錄
						p.setChildrenNum(p.getChildren().size());
						oldModel.setParent(p);
						op.removeChildren(oldModel);//原來的父目錄要刪除兒子。
						op.setChildrenNum(op.getChildren().size());
					}else{
						;//相等，就沒有必要處理。
					}
				}else{//op是null，原來是頂級目錄
					p.addChildren(oldModel);//新的父目錄
					p.setChildrenNum(p.getChildren().size());
					oldModel.setParent(p);
				}
			}
			T mm = super.smartUpdateBaseModel((T) model);
			mm.setChildrenNum(mm.getChildren().size());
			return mm;
	}
	
	@Override
	public void smartRemoveBaseModel(T model) {
		if(checkHasChildren((TreeModel<T>)model)){
			return;
		}
		TreeModel<T> p = model.getParent();
		if(p != null){
			p.removeChildren(model);
			p.setChildrenNum(p.getChildren().size());
			merge((T) p);
		}
		super.smartRemoveBaseModel(model);
	}
	
	@Transactional
	public T remove(TreeModel<T> baseModel) {
		EntityManager em = emp.get();
		T bm = em.find(this.persistentClass, baseModel.getId()); 
		if(bm.getParent() != null){
			bm.getParent().removeChildren(bm);
		}
		bm.setParent(null);
		em.remove(bm);
		return bm;
	}
	
	@Transactional
	public T remove(int modelId) {
		EntityManager em = emp.get();
		T bm = em.find(this.persistentClass, modelId); 
		bm.setParent(null);
		em.remove(bm);
		return bm;
	}


	private boolean checkHasChildren(TreeModel<T> tm) {
		if(tm.getChildren().size() > 0){
			injector.getInstance(ErrorMessages.class).addError(new SmartError("请先删除子目录！",ServerErrorCode.DEPENDENCY_ERROR));
			return true;
		}
		return false;
	}
	
	/**
	 * 
	 * @param other
	 * @return
	 * 要不要包括自己呢？现在是包括的。
	 */
	protected String getParentPath(TreeModel<T> treeModel) {
		List<TreeModel<T>> parents = new ArrayList<TreeModel<T>>();
		while(treeModel != null){
			parents.add(treeModel);
			treeModel = treeModel.getParent();
		}
		String s = ",";
		for (TreeModel<T> baseModel : parents) {
			s += baseModel.getId() + ",";
		}
		return s;
	}

}